import {useState, useRef, useEffect} from 'react';

function getProp(object, propPath='') {
  const path = propPath.split('.').reverse();

  let curr = object;
  while(curr && path.length > 0) {
    curr = curr?.[path.pop()];
  }

  return curr;
}

function setProp(object, propPath="", newValue) {

  const path = propPath.split('.').reverse();

  let curr = object;
  while(curr && path.length > 1) {
    const next = path.pop();
    curr[next] ?? (curr[next] = {});
    curr = curr[next];
  }

  console.log('SETPROP', curr, path, newValue);
  curr[path.pop()] = newValue; 
}

function compSign(A, B) {
  return A > B ? 1 : A < B ? -1 : 0;
}

export default function(origData) {

  const [colFilters, setColFilters] = useState({});
  const [colSorts, setColSorts] = useState({});

  const tempEditRef = useRef({});

  useEffect(() => {
    setColFilters({});
    setColSorts({});
  }, [origData]);

  const filter = (key, pattern) => {
    console.log('FILTER', pattern, 'APPLIED TO', key);
    if (pattern === '' || pattern === undefined) {
      const {[key]:_, ...restFilters} = colFilters;
      setColFilters(restFilters);
    } else {
      setColFilters({...colFilters, [key]: pattern});
    }
  }

  const sort = (key) => {
    const order = colSorts[key];
    const nextOrder = order === 'ascending'
    ? 'descending'
    : order === 'descending'
    ? undefined
    : 'ascending'
    
    if (nextOrder === undefined) {
      setColFilters({});
    } else {
      setColSorts({[key]: nextOrder})
    }
  }

  let data;
  let filterApplied;

  if (Object.keys(colFilters).length === 0 && Object.keys(colSorts).length === 0) {

    data = origData;
    filterApplied = false;

  } else {
    
    data = [...origData];
    filterApplied = true;
    
    for (let key of Object.keys(colFilters)){
      data = data.filter(elem => {
        return getProp(elem, key)?.toString().includes(colFilters[key]);
      })
    }
  
    for (let key of Object.keys(colSorts)){
      data.sort(
        (elemA, elemB) => {
          const valA = getProp(elemA, key);
          const valB = getProp(elemB, key);
          return colSorts[key] === 'descending'
          ? compSign(valB, valA)
          : compSign(valA, valB)
        }
      );
    }
  }

  const editMethods = {
    insert: (index) => {
      console.log(`INSERT`, index);
      data.insert(new (data[0].constructor)(), index);
    },
    remove: (index) => {
      data.remove(index);
    },
    moveBack: (index) => {
      data.moveBack(index);
    },
    moveFore: (index) => {
      data.moveFore(index);
    },
    openEdit: (index) => {
      tempEditRef.current[index] = {};
    },
    saveEdit: (index) => {
      console.log('SAVE EDIT:', tempEditRef.current[index]);
      for (let [propPath, value] of Object.entries(tempEditRef.current[index])) {
        setProp(data[index], propPath, value);
      }
    }
  };

  const updateProp = (index, propPath, value) => {
    console.log("UPDATE PROP", index, propPath, value);
    tempEditRef.current[index][propPath] = value;
  };


  return {
    data,
    filterApplied,
    sort,
    filter,
    updateProp,
    editMethods
  }
}
